package com.ppch.wuwamanus.agent;

import com.ppch.wuwamanus.advisors.DatabaseChatMemory;
import com.ppch.wuwamanus.advisors.MyLoggerAdvisor;
import com.ppch.wuwamanus.agent.prompt.SystemPrompt;
import com.ppch.wuwamanus.config.CosClientConfig;
import com.ppch.wuwamanus.config.FileUtils;
import com.ppch.wuwamanus.mapper.ChatHistoryMapper;
import com.ppch.wuwamanus.service.ChatHistoryService;
import lombok.Setter;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;


/**
 * Package:ppch-ai-agent
 * ClassName:TestManus
 *
 * @Author 泡泡茶壶
 * @Create 2025/7/31 21:21
 * @Version 1.0
 * Description:
 * 带有自主规划能力的《鸣潮》游戏攻略智能体
 * 1.可以根据任务自主分解任务、制定计划、选择工具并一步步执行，直到任务完成。
 * 2.通过系统提示词实现 COT 思维链。
 * 3.实现 Agent Loop 执行循环：可以在用户没有输入的情况下，自主重复执行和工具调用直到任务完成。
 * 4.实现 ReAct 模式：思考——>行动——>观察——>循环迭代，
 * 将问题拆分为多个步骤->调用外部工具执行动作->获取工具调用结果反馈给智能体，智能体做出下一步决策->循环直至任务完成
 * 5.使用 List<Message> memoryList = new ArrayList<>() 实现上下文存储。
 * 6.实现工具调用。
 * 7.在 ReActAgent 中添加循环检测和处理机制，防止智能体陷入无限循环。
 * 8.实现支持智能体交互式执行：向用户询问信息并获取用户反馈，通过新增 AskHumanTool 工具实现。
 *      TODO：接入 RAG 知识库
 *      TODO：实现搜索攻略并生成对应的 PDF 文件
 *      TODO：实现抽卡分析功能
 */
@Component
@Setter
//把Spring Bean作用域设置为Request，每次HTTP请求都会创建一个新的实例，
//并且使用CGLIB代理来注入该Bean（因为proxyMode为TARGET_CLASS，表示使用类代理），
//因为不是Spring管理的普通对象无法直接注入，只能使用@Value注解从请求参数中获取值。
@Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class GameAssistantManus extends ToolCallAgent {

    /**
     * 初始化智能体
     *
     * @param allTools                         自定义工具列表（自动注入）
     * @param toolCallbackProvider             MCP 服务（自动注入）
     * @param dashscopeChatModel               灵积大模型（自动注入）
     */
    public GameAssistantManus( ToolCallback[] allTools, ToolCallbackProvider toolCallbackProvider,
                              ChatModel dashscopeChatModel,FileUtils fileUtils,
                               @Value("#{request.getParameter('chatId')}") Long chatId,
                               @Value("#{request.getParameter('userId')}") Long userId,
                              @Value("#{request.getParameter('chatMemoryRetrieveSize')}") int chatMemoryRetrieveSize,
                              ChatHistoryMapper chatHistoryMapper, CosClientConfig cosClientConfig,
                               Advisor dashScopeRetrievalAugmentationAdvisor,
                               ChatHistoryService chatHistoryService
                               ) {
        //调用父类ToolCallAgent构造器，完成初始化，给 ToolCallback[]，ToolCallbackProvider 赋值
        super(allTools, toolCallbackProvider,fileUtils,chatHistoryMapper,cosClientConfig,chatHistoryService,userId);
        this.setName("gameAssistantManus");
        //设置对话 ID 和关联上下文的条数
        this.setChatId(chatId);
        //设置关联的上下文大小
        this.setChatMemoryRetrieveSize(chatMemoryRetrieveSize);
        //TODO：优化提示词
        this.setSystemPrompt(SystemPrompt.SYSTEM_PROMPT);
        this.setNextStepPrompt("");
        //创建自定义基于MySql的对话记忆
        DatabaseChatMemory databaseChatMemory = new DatabaseChatMemory(chatHistoryService);
        databaseChatMemory.setCurrentUserId(userId);
        //创建 ChatClient 对象
        ChatClient chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultAdvisors(
                        //基于阿里云百炼云知识库的检索增强顾问
                        dashScopeRetrievalAugmentationAdvisor,
                        //自定义日志记录顾问
                        new MyLoggerAdvisor(),
                        //基于MySql数据库的对话记忆顾问
                        new MessageChatMemoryAdvisor(databaseChatMemory)
                )
                //设置对话记忆参数：会话ID，关联上下文大小
                .defaultAdvisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                                .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, chatMemoryRetrieveSize))
                .build();
        this.setChatClient(chatClient);
        //设置执行的最大步骤数
        this.setMaxSteps(3);
    }



}
